Это очень показательное сообщение. Сообщение WM_CTLCOLOR посылается каждый раз когда само окно или одно из его средств управления должно перерисоваться. В ответ должна вернуться кисть для перерисовки.
Итак, давайте изучать. Создаем приложение на базе MFC AppWizard с именем TestDlg как диалоговое окно. Для класса CTestDlgDlg вызовем Add Windows Message Handler. Найдем там сообщение WM_CTLCOLOR и добавим его обработку к классу.
////////////////////////////////
// CTestDlgDlg dialog
class CTestDlgDlg : public CDialog
{
......
afx_msg HCURSOR OnQueryDragIcon();
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
HBRUSH CTestDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
// TODO: Return a different brush if the default is not desired
return hbr;
}
Давайте заменим кисть, чтобы окрасить окно в разные цвета:
HBRUSH CTestDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
pDC->SetBkColor(RGB(127,127,127));
return (HBRUSH)::GetStockObject(GRAY_BRUSH);
}
Если Вы сейчас запустите приложение, то окно будет серым. Это нормально, мы так и хотели. Поместите на диалоговую панель Edit Box, Static Box. Запустите приложение. Они тоже будут серыми. Эти элементы управления спрашивают кисть для покраски у родителя, то есть они посылают сообщение диалоговому окну с просьбой указать чем красить. Давайте попробуем это исправить.
HBRUSH CTestDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
if (CTLCOLOR_EDIT == nCtlColor)
{
pDC->SetTextColor(RGB(0,0,0));
pDC->SetBkColor(RGB(255,255,255));
return (HBRUSH)::GetStockObject(WHITE_BRUSH);
}
if (CTLCOLOR_STATIC == nCtlColor)
{
pDC->SetBkColor(RGB(255,0,255));
return (HBRUSH)::GetStockObject(GRAY_BRUSH);
}
pDC->SetBkColor(RGB(127,127,127));
return (HBRUSH)::GetStockObject(GRAY_BRUSH);
}
Вот теперь совсем другое дело. Белое поле редактирования, красный статический элемент. Работает. А что если у нас много элементов управления ??? Как разобраться какой красить ??? Поместите второй элемент управления и код для него:
HBRUSH CTestDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
if (CTLCOLOR_EDIT == nCtlColor)
{
UINT id = pWnd->GetDlgCtrlID();
if (id == IDC_EDIT2)
{
pDC->SetTextColor(RGB(0,0,0));
return (HBRUSH)::GetStockObject(WHITE_BRUSH);
}
if ( id == IDC_EDIT1)
{
pDC->SetTextColor(RGB(0,0,0));
return (HBRUSH)::GetStockObject(DKGRAY_BRUSH);
}
}
if (CTLCOLOR_STATIC == nCtlColor)
{
pDC->SetBkColor(RGB(255,0,255));
return (HBRUSH)::GetStockObject(GRAY_BRUSH);
}
pDC->SetBkColor(RGB(127,127,127));
return (HBRUSH)::GetStockObject(GRAY_BRUSH);
}
Как видите разобраться можно. Есть следующие идентификаторы:
Все это хорошо, только сейчас мы реализовали все как при программировании на WIN32 API без всяких там классов. Но в реальности правильно, если за закраску будет отвечать сам класс. Так должно быть. Не должен диалог отвечать за закраску своих элементов. Иначе при большом количестве идентификаторов ваша функция OnCtlColor() превратится в сплошной switch. Об этом в следующем шаге. А пока посмотрите на результат. Он у Вас должен быть такой же.
